package com.cicadalane.androlate;

/*
 * Copyright (C) 2011 cicada.software@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.statushandlers.StatusManager;
import org.xml.sax.SAXException;

import com.cicadalane.androlate.statushandlers.AndrolateStatus;

/*
 * Find and load resource XML files
 */
class LoadResourceFilesPage extends AndrolateWizardPage implements Listener {
	private Table mFileList = null;
	private Table mIgnoreStringTable = null;
	private Button mSelectAllFilesButton = null;
	private Button mSelectAllIgnoreButton = null;
	private Button mSelectAllTranslateButton = null;
	private Table mTranslateStringTable = null;
	private AndrolateOperation selectedOperation = null;

	protected LoadResourceFilesPage(String pageName) {
		super(pageName);
		setTitle(pageName);
		setDescription("Select the resources you would like translated");
		setPageComplete(false);
	}

	private void bind(Androlate a, Androlate saved) {
		mFileList.removeAll();
		List<AndrolateOperation> operations = a.getOperations();
		for (AndrolateOperation o : operations) {
			String filename = o.getFilename();
			java.io.File projectFilePath = getAndrolateWizard()
					.getProjectPath().toFile();
			String filenameDisplay = AndrolateApplication.stringIntersection(
					filename, projectFilePath.getAbsolutePath());

			TableItem fileListTi = new TableItem(mFileList, SWT.NONE);
			fileListTi.setText(new String[] { filenameDisplay });
			fileListTi.setData(o);
			if (saved != null) {
				List<AndrolateOperation> savedOperations = saved
						.getOperations();
				for (AndrolateOperation savedOperation : savedOperations) {
					if (o.getFilename().equals(savedOperation.getFilename())) {
						fileListTi.setChecked(true);
					}
				}
			}
		}

	}

	@Override
	public void createControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);

		GridLayout gl = new GridLayout();
		composite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
				true, false));
		gl.numColumns = 2;
		gl.makeColumnsEqualWidth = true;
		composite.setLayout(gl);

		Label l = new Label(composite, 0);
		l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		((GridData) l.getLayoutData()).horizontalSpan = 2;
		l
				.setText("Check the resource files and values below to select which strings will be sent for translation");

		createFileListTable(composite);

		TabFolder tabFolder = new TabFolder(composite, SWT.NONE);
		TabItem tabTranslateStringsItem = new TabItem(tabFolder, SWT.NULL);
		tabTranslateStringsItem.setText("Translate Strings");

		TabItem tabIgnoreStringsItem = new TabItem(tabFolder, SWT.NULL);
		tabIgnoreStringsItem.setText("Ignore Strings");

		Group translateGroup = createStringListTable(tabFolder,
				AndrolateApplication.STRINGLIST_TABLE_MODE_TRANSLATE);
		tabTranslateStringsItem.setControl(translateGroup);

		Group ignoreGroup = createStringListTable(tabFolder,
				AndrolateApplication.STRINGLIST_TABLE_MODE_IGNORE);
		tabIgnoreStringsItem.setControl(ignoreGroup);

		tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
		((GridData) tabFolder.getLayoutData()).horizontalSpan = 2;

		setControl(composite);

		loadResources();
	}

	private void createFileListTable(final Composite composite) {
		Group fileListGroupBox = new Group(composite, SWT.SHADOW_ETCHED_IN);
		fileListGroupBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		((GridData) fileListGroupBox.getLayoutData()).horizontalSpan = 2;
		FillLayout rowLayout = new FillLayout();
		// rowLayout.spacing = 1;
		rowLayout.type = SWT.VERTICAL;
		// fileListGroupBox.setLayout(rowLayout);
		fileListGroupBox.setLayout(new GridLayout());
		fileListGroupBox.setText("Select Resource Files:");

		mSelectAllFilesButton = new Button(fileListGroupBox, SWT.CHECK);
		mSelectAllFilesButton.setText("Select / Deselect All");
		mSelectAllFilesButton.addListener(SWT.Selection, this);

		mFileList = new Table(fileListGroupBox, SWT.SINGLE | SWT.V_SCROLL
				| SWT.H_SCROLL | SWT.CHECK);

		mFileList.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		((GridData) mFileList.getLayoutData()).horizontalSpan = 2;
		// mFileList.setLayout(new FillLayout(SWT.HORIZONTAL));
		mFileList.removeAll();
		mFileList.addListener(SWT.Selection, this);
		fileListGroupBox.pack();
	}

	private Group createStringListTable(final Composite composite,
			final int mode) {
		Group groupBox = new Group(composite, SWT.SHADOW_ETCHED_IN);
		groupBox.setLayoutData(new GridData(GridData.FILL_BOTH));
		((GridData) groupBox.getLayoutData()).horizontalSpan = 1;
		FillLayout rowLayout = new FillLayout();
		// rowLayout.spacing = 1;
		rowLayout.type = SWT.VERTICAL;
		// fileListGroupBox.setLayout(rowLayout);
		groupBox.setLayout(new GridLayout());
		if (mode == AndrolateApplication.STRINGLIST_TABLE_MODE_TRANSLATE) {
			groupBox.setText("Select the strings to translate:");
			mSelectAllTranslateButton = new Button(groupBox, SWT.CHECK);
			mSelectAllTranslateButton.setText("Select / Deselect All");
			mSelectAllTranslateButton.addListener(SWT.Selection, this);
		} else {
			groupBox
					.setText("Select strings that you do NOT want to translate (ignored):");
			mSelectAllIgnoreButton = new Button(groupBox, SWT.CHECK);
			mSelectAllIgnoreButton.setText("Select / Deselect All");
			mSelectAllIgnoreButton.addListener(SWT.Selection, this);
		}

		Table table = new Table(groupBox, SWT.MULTI | SWT.V_SCROLL
				| SWT.H_SCROLL | SWT.CHECK);
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		table.setLayoutData(new GridData(GridData.FILL_BOTH));
		((GridData) table.getLayoutData()).heightHint = Math.round(getShell()
				.getSize().y / 4);
		((GridData) table.getLayoutData()).horizontalSpan = 1;

		for (int i = 0; i < AndrolateApplication.STRINGLIST_TABLE_TITLES.length; i++) {
			TableColumn column = new TableColumn(table, SWT.NONE);
			column.setText(AndrolateApplication.STRINGLIST_TABLE_TITLES[i]);
		}
		table.addListener(SWT.Selection, this);
		if (mode == AndrolateApplication.STRINGLIST_TABLE_MODE_TRANSLATE) {
			mTranslateStringTable = table;
		} else {
			mIgnoreStringTable = table;
		}
		return groupBox;
	}

	@Override
	public void handleEvent(Event event) {
		if (event.widget == mSelectAllFilesButton) {
			getAndrolate().setOption(Androlate.OPTION_KEY_TRANSLATE_EVERYTHING,
					mSelectAllFilesButton.getSelection());
			for (TableItem ti : mFileList.getItems()) {
				ti.setChecked(mSelectAllFilesButton.getSelection());
			}
		}
		if (event.widget == mSelectAllTranslateButton) {
			for (TableItem ti : mTranslateStringTable.getItems()) {
				ti.setChecked(mSelectAllTranslateButton.getSelection());
			}
		}
		if (event.widget == mSelectAllIgnoreButton) {
			for (TableItem ti : mIgnoreStringTable.getItems()) {
				ti.setChecked(mSelectAllIgnoreButton.getSelection());
			}
		}
		if (event.widget == mTranslateStringTable
				|| event.widget == mIgnoreStringTable) {
			if (event.detail != SWT.CHECK) {
				setPageComplete(validatePage());
				return;
			}
			if (!(event.item instanceof TableItem)) {
				setPageComplete(validatePage());
				return;
			}
			int mode = AndrolateApplication.STRINGLIST_TABLE_MODE_TRANSLATE;
			if (event.widget == mIgnoreStringTable)
				mode = AndrolateApplication.STRINGLIST_TABLE_MODE_IGNORE;

			TableItem tableItem = (TableItem) event.item;
			if (tableItem.getData() == null
					|| !(tableItem.getData() instanceof StringData)) {
				setPageComplete(validatePage());
				return;
			}

			/* add or remove StringData to operation */
			StringData s = (StringData) tableItem.getData();
			ArrayList<StringData> sl = null;
			if (selectedOperation != null) {
				if (mode == AndrolateApplication.STRINGLIST_TABLE_MODE_TRANSLATE) {
					sl = selectedOperation.getTranslateList();
				} else if (mode == AndrolateApplication.STRINGLIST_TABLE_MODE_IGNORE) {
					sl = selectedOperation.getIgnoreList();
				}

				if (sl != null) {
					if (tableItem.getChecked()) {
						if (!sl.contains(s))
							sl.add(s);
						else if (sl.contains(s))
							sl.remove(s);
					} else {
						if (sl.contains(s))
							sl.remove(s);
					}
				}
			}
		}
		if (event.widget == mFileList) {
			if (!(event.item instanceof TableItem)) {
				setPageComplete(validatePage());
				return;
			}
			mSelectAllTranslateButton.setSelection(false);
			mSelectAllIgnoreButton.setSelection(false);
			TableItem tableItem = (TableItem) event.item;
			if (tableItem.getData() == null
					|| !(tableItem.getData() instanceof AndrolateOperation)) {
				setPageComplete(validatePage());
				return;
			}

			AndrolateOperation operation = (AndrolateOperation) tableItem
					.getData();

			selectedOperation = operation;
			if (event.detail == SWT.CHECK) {
				setPageComplete(validatePage());
				return;
			}

			mTranslateStringTable.removeAll();
			mIgnoreStringTable.removeAll();
			ArrayList<StringData> allStringsList = (ArrayList<StringData>) operation
					.getAllStringsList();
			for (StringData s : allStringsList) {
				String name = s.getName();
				if (name == null || name.isEmpty())
					continue;

				TableItem newTranslateTableItem = new TableItem(
						mTranslateStringTable, SWT.NONE);
				newTranslateTableItem.setText(
						AndrolateApplication.STRINGLIST_TABLE_NAME_INDEX, name);
				newTranslateTableItem.setText(
						AndrolateApplication.STRINGLIST_TABLE_VALUE_INDEX, s
								.getValue());
				newTranslateTableItem.setData(s);

				TableItem newIgnoreTableItem = new TableItem(
						mIgnoreStringTable, SWT.NONE);
				newIgnoreTableItem.setText(
						AndrolateApplication.STRINGLIST_TABLE_NAME_INDEX, name);
				newIgnoreTableItem.setText(
						AndrolateApplication.STRINGLIST_TABLE_VALUE_INDEX, s
								.getValue());
				newIgnoreTableItem.setData(s);

				if (AndrolateApplication.containsName(selectedOperation
						.getTranslateList(), name)) {
					newTranslateTableItem.setChecked(true);
				}

				if (AndrolateApplication.containsName(selectedOperation
						.getIgnoreList(), name)) {
					newIgnoreTableItem.setChecked(true);
				}
			}
			for (TableColumn c : mTranslateStringTable.getColumns())
				c.pack();

			for (TableColumn c : mIgnoreStringTable.getColumns())
				c.pack();
		}

		setPageComplete(validatePage());
	}

	private void loadResources() {
		getAndrolateWizard().getAndrolateApplication();
		File[] resourceXmlfiles = FileFind.find(AndrolateApplication
				.getResValuesPath().toFile(),
				new ExtensionFilenameFilter("xml"), true);
		Androlate saved = null;
		try {
			getAndrolateApplication().createOperations(resourceXmlfiles);

			File configFile = getAndrolateWizard().getConfigFile();
			if (configFile.exists()) {
				try {
					saved = new Androlate();
					saved.loadFromFile(configFile);

					AndrolateApplication.mergeAndrolateObjects(saved,
							getAndrolate());
				} catch (Exception e) {
					Status status = new Status(IStatus.ERROR,
							Activator.PLUGIN_ID,
							AndrolateStatus.ERROR_IO_EXCEPTION,
							"Error loading saved settings", e.getCause());
					StatusManager.getManager().handle(status,
							StatusManager.BLOCK);
				}
			}
		} catch (ParserConfigurationException e) {
			Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID,
					AndrolateStatus.ERROR_PARSER_CONFIGURATION_EXCEPTION,
					"Error loading resources", e.getCause());
			StatusManager.getManager().handle(status, StatusManager.BLOCK);
		} catch (SAXException e) {
			Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID,
					AndrolateStatus.ERROR_SAX_EXCEPTION,
					"Error loading resources", e.getCause());
			StatusManager.getManager().handle(status, StatusManager.BLOCK);
		} catch (IOException e) {
			Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID,
					AndrolateStatus.ERROR_IO_EXCEPTION,
					"Error loading resources", e.getCause());
			StatusManager.getManager().handle(status, StatusManager.BLOCK);
		} catch (TransformerException e) {
			Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID,
					AndrolateStatus.ERROR_TRANSFORMER_EXCEPTION,
					"Error loading resources", e.getCause());
			StatusManager.getManager().handle(status, StatusManager.BLOCK);
		}

		bind(getAndrolate(), saved);
	}

	@Override
	public void onEnterPage() {
		// TODO Auto-generated method stub
		super.onEnterPage();
	}

	/*
	 * Returns true when a resource and at least one string is selected for
	 * translation
	 */
	private boolean validatePage() {
		boolean result = false;

		Androlate a = getAndrolate();
		if (a == null)
			return false;

		for (TableItem ti : mFileList.getItems()) {
			AndrolateOperation op = (AndrolateOperation) ti.getData();
			if (op == null)
				continue;
			if (ti.getChecked()) {
				if (!AndrolateApplication.contains(a.getOperations(), op))
					a.getOperations().add(op);
			} else {
				if (AndrolateApplication.contains(a.getOperations(), op))
					a.getOperations().remove(op);
			}
		}

		for (TableItem ti : mFileList.getSelection()) {
			AndrolateOperation op = (AndrolateOperation) ti.getData();
			if (op == null)
				continue;
			if (ti.getChecked()) {
				if (!AndrolateApplication.contains(a.getOperations(), op))
					a.getOperations().add(op);
			} else {
				if (AndrolateApplication.contains(a.getOperations(), op))
					a.getOperations().remove(op);
			}
			for (TableItem tiTranslate : mTranslateStringTable.getItems()) {
				StringData s = (StringData) tiTranslate.getData();
				if (tiTranslate.getChecked()) {
					if (!AndrolateApplication.containsStringData(op
							.getTranslateList(), s)) {
						op.getTranslateList().add(s);
					}
				} else {
					if (AndrolateApplication.containsStringData(op
							.getTranslateList(), s)) {
						AndrolateApplication.removeStringData(op
								.getTranslateList(), s);
					}
				}
			}
			for (TableItem tiIgnore : mIgnoreStringTable.getItems()) {
				StringData s = (StringData) tiIgnore.getData();
				if (tiIgnore.getChecked()) {
					if (!AndrolateApplication.containsStringData(op
							.getIgnoreList(), s)) {
						op.getIgnoreList().add(s);
					}
				} else {
					AndrolateApplication
							.removeStringData(op.getIgnoreList(), s);
				}
			}
		}

		List<AndrolateOperation> operations = a.getOperations();
		if (operations == null || operations.size() == 0)
			return false;

		for (AndrolateOperation o : operations) {
			if (!(o.getTranslateList() == null || o.getTranslateList().size() == 0)) {
				result = true;
				break;
			}
		}

		return result;
	}
}